package com.asia5b.a5mall.middleware.utils

/**
 * Created by zhangyuncai on 2019/12/21.
 * @Note   扩展方法Koltin文件
 */

import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.databinding.ObservableField
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.alibaba.android.arouter.facade.Postcard
import com.alibaba.android.arouter.launcher.ARouter
import com.asia5b.a5bmall.resource.ActCons
import com.asia5b.a5bmall.resource.ResString
import com.asia5b.a5mall.middleware.R
import com.asia5b.a5mall.middleware.base.BaseApplication
import com.asia5b.a5mall.middleware.config.GlideEngine
import com.asia5b.a5mall.middleware.config.UserRepository
import com.asia5b.a5mall.middleware.model.shop.AbsGoodsModel
import com.luck.picture.lib.PictureSelector
import com.luck.picture.lib.config.PictureConfig
import com.luck.picture.lib.config.PictureMimeType
import com.luck.picture.lib.engine.ImageEngine
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.listener.OnResultCallbackListener
import com.tbruyelle.rxpermissions2.RxPermissions
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import okhttp3.ResponseBody
import org.greenrobot.eventbus.EventBus
import org.json.JSONArray
import org.json.JSONObject
import timber.log.Timber
import java.lang.ref.WeakReference
import java.nio.charset.Charset
import java.util.*
import kotlin.collections.ArrayList

/**
 * 绑定字段 指定泛型
 */
typealias ObserableString = ObservableField<String>


fun dddLog(message: String) {
    Timber.d("--->>>>>>>>---$message")
}


/**
 * @Note   显示Toast信息
 * @param  message 需要显示的信息
 */
fun showMessage(message: String) {
    ToastUtil.showToast(message)
}

fun showMessage(@StringRes message: Int) {
    ToastUtil.showToast(ResString.get(message))
}

/**
 * @Note   数据类型转换
 * @return 转换后的值
 */
fun <T> Any.to(): T {
    return this as T
}


/**
 * @Note   通过ARouter框架检索对象，并实例化
 * @param  path 对象注册到ARouter的路径
 */
fun <T> acquireInstance(path: String): T {
    return ARouter.getInstance().build(path).navigation() as T
}


/**
 * Created by zhangyuncai on 2019/10/19.
 */
/**
 * @Note   跳转页面Activity扩展方法
 * @param  path Activity注册到ARouter中的路径
 * @param  _block 更多操作
 * @param  requstCode 返回码
 */
fun AppCompatActivity.push(path: String, _block: ((Postcard) -> Unit)? = null, requstCode: Int = -1, isNeedLogin: Boolean = false) {
    if (isNeedLogin && !UserRepository.isLogin()) {
        ARouter.getInstance().build(ActCons.LoginActivity)/*.withTransition(R.anim.push_left_in, R.anim.push_left_out)*/
                .then { postcard ->
                    _block?.invoke(postcard)
                }
                .navigation(this)
        return
    }
    val engine = ARouter.getInstance().build(path)/*.withTransition(R.anim.push_left_in, R.anim.push_left_out)*/.then { postcard ->
        _block?.invoke(postcard)
    }
    if (requstCode == -1) {
        engine.navigation(this)
    } else {
        engine.navigation(this, requstCode)
    }
}


/**
 * @Note   跳转页面Activity扩展方法
 * @param  path Activity注册到ARouter中的路径
 * @param  _block 更多操作
 * @param  requstCode 返回码
 */
fun Activity.push(path: String, _block: ((Postcard) -> Unit)? = null, requstCode: Int = -1, isNeedLogin: Boolean = false) {
    if (isNeedLogin && !UserRepository.isLogin()) {
        ARouter.getInstance().build(ActCons.LoginActivity)/*.withTransition(R.anim.push_left_in, R.anim.push_left_out)*/
                .then { postcard ->
                    _block?.invoke(postcard)
                }
                .navigation(this)
        return
    }
    val engine = ARouter.getInstance().build(path)/*.withTransition(R.anim.push_left_in, R.anim.push_left_out)*/.then { postcard ->
        _block?.invoke(postcard)
    }
    if (requstCode == -1) {
        engine.navigation(this)
    } else {
        engine.navigation(this, requstCode)
    }

}

/**
 * @Note   跳转页面 V4 Fragment扩展方法
 * @param  path Activity注册到ARouter中的路径
 * @param  _block 更多操作
 */
fun Fragment.push(path: String, _block: ((Postcard) -> Unit)? = null, isNeedLogin: Boolean = false) {
    if (isNeedLogin && !UserRepository.isLogin()) {
        ARouter.getInstance().build(ActCons.LoginActivity)/*.withTransition(R.anim.push_left_in, R.anim.push_left_out)*/
                .then { postcard ->
                    _block?.invoke(postcard)
                }
                .navigation(activity)
        return
    }
    ARouter.getInstance().build(path)/*.withTransition(R.anim.push_left_in, R.anim.push_left_out)*/.then { postcard ->
        _block?.invoke(postcard)
    }.navigation(activity)
}

/**
 * @Note   Activity 退出扩展方法
 */
fun AppCompatActivity.pop() {
    finish()
//    overridePendingTransition(R.anim.push_right_in, R.anim.push_right_out)
}

/**
 * @Note   用于代码规范化 有助于代码美观 一般用于配置对象时对代码格式化
 *         示例: val linearLayout = LinearLayout(context).then {
 *                  lay ->
 *                  lay.orientation = LinearLayout.HORIZONTAL
 *                  lay.setBackgroundColor(Color.RED)
 *              }.removeAllViews()
 * @param  _block 回调
 */
inline fun <T : Any> T.then(_block: (T) -> Unit): T {
    _block.invoke(this)
    return this
}

/**
 * @Note   用于代码格式化 与then不同的是 该方法不继续传递self 一般用于格式化对象初始化代码
 *         示例: val view = View(context).more {
 *                  self ->
 *                  self.setBackgroundColor(Color.BLUE)
 *                  self.setFadingEdgeLength(1)
 *                  self.setOnClickListener{}
 *              }
 * @param  _block 回调
 */
inline fun <T : Any> T.more(_block: (T) -> Unit) {
    _block.invoke(this)
}


/**
 * @Note   获取事件序列中心
 * @return EventBus事件中心
 */
fun getEventBus(): EventBus {
    return EventBus.getDefault()
}

/**
 * @Note   当变量为空时执行
 * @param  _block 回调
 */
inline fun Any?.haventDo(_block: () -> Unit) {
    if (this == null) {
        _block.invoke()
        return
    } else if (this is String) {
        if (this == "") {
            _block.invoke()
        }
    }
}

/**
 * @Note   当一个序列 都为空时 执行该回调
 * @param  array 需要判断空的序列
 * @param  _block 回调
 */
inline fun haventDo(vararg array: Any?, _block: () -> Unit) {
    var has = false
    for (any in array) {
        if (any != null) {
            has = true
            if (any is String) {
                if (any == "") {
                    has = false
                }
            }
        } else {
            has = false
        }
    }
    if (!has) {
        _block.invoke()
    }
}

/**
 * @Note   当变量不为空时执行
 * @param  _block 回调
 */
inline fun Any?.haveDo(_block: () -> Unit) {
    if (this != null) {
        if (this is String) {
            if (this == "") {
                return
            }
        }
        _block.invoke()
    }
}

/**
 * @Note   当一个序列 都不为空时 执行该回调
 * @param  array 需要判断空的序列
 * @param  _block 回调
 */
inline fun haveDo(vararg array: Any?, _block: () -> Unit) {
    var has = true
    for (any in array) {
        if (any == null) {
            has = false
        } else if (any is String) {
            if (any == "") {
                has = false
            }
        }
    }
    if (has) {
        _block.invoke()
    }
}

/**
 * @Note   通过context获取颜色
 * @param  rid  颜色索引ID
 */
fun Context.getColorCompatible(rid: Int): Int {
    return ContextCompat.getColor(this, rid)
}

/**
 * @Note   非入侵式，setOnScrollListener兼容低版本实现
 * @param  call 滑动回调
 */
inline fun View.setOnScrollObserver(crossinline call: (scrollX: Int, scrollY: Int, oldScrollX: Int, oldScrollY: Int) -> (Unit)) {
    var oldScrollX = 0
    var oldScrollY = 0
    this.viewTreeObserver.addOnScrollChangedListener {
        call.invoke(scrollX, scrollY, oldScrollX, oldScrollY)
        oldScrollX = scrollX
        oldScrollY = scrollY
    }
}

/**
 * @Note   快速判断语法糖
 * @param  trueDo  为true时调用
 * @param  falseDo 为false时调用
 */
fun Boolean.judge(trueDo: (() -> (Unit))? = null, falseDo: (() -> (Unit))? = null) {
    if (this) {
        trueDo?.invoke()
    } else {
        falseDo?.invoke()
    }
}

/**
 * @Note   快速判断语法糖
 * @param  visib  true/显示 false/隐藏 defaultVisib/不显示透明
 */
fun View.judge(visib: Boolean, defaultVisib: Int? = null) {
    visibility = if (visib) {
        View.VISIBLE
    } else {
        View.GONE
    }
//    visibility = (visib).judge(View.VISIBLE, defaultVisib ?: View.GONE)
}

/**
 * @Note   快速判断语法糖
 * @param  trueValue  为true时抛出
 * @param  falseValue 为false时抛出
 */
fun <T> Boolean.judge(trueValue: T, falseValue: T): T {
    return if (this) {
        trueValue
    } else {
        falseValue
    }
}

/**
 * @Note   快速重新定义LayoutParams重新布局
 * @param  layout 重新布局回调
 */
inline fun <T : ViewGroup.LayoutParams> View.reLayout(layout: ((params: T) -> (Unit))) {
    var params = (this.layoutParams as T)
    layout(params)
    this.layoutParams = params
}

/**
 * @Note   顺序执行补间动画 且可拦截
 * @param  animList 动画列表
 * @param  interceptor 拦截器
 */
fun View.animSequentialStart(animList: ArrayList<Animation>, interceptor: ((index: Int, state: Int) -> (Boolean))? = null) {

    var index = 0

    var listener = object : Animation.AnimationListener {
        override fun onAnimationRepeat(animation: Animation?) {
            val flag = interceptor?.invoke(index, 1)
            flag?.judge(trueDo = {
                animation?.cancel()
            })
        }

        override fun onAnimationEnd(animation: Animation?) {
            if (index != animList.size - 1) {
                animList[index].cancel()
            }
            val flag = interceptor?.invoke(index, 2)
            index += 1
            flag?.judge(trueDo = {
                animation?.cancel()
            }, falseDo = {
                if (index < animList.size) {
                    animList[index].setAnimationListener(this)
                    startAnimation(animList[index])
                }
            })
        }

        override fun onAnimationStart(animation: Animation?) {
            val flag = interceptor?.invoke(index, 3)
            flag?.judge(trueDo = {
                animation?.cancel()
            })
        }
    }
    animList[index].setAnimationListener(listener)
    startAnimation(animList[index])
}


/**
 * @Note   Vlayout获取屏幕上可见第一个Item的位置
 */
fun LinearLayoutManager.getScollYDistance(): Int {
    val position = findFirstVisibleItemPosition()
    val firstVisiableChildView = findViewByPosition(position)
    val itemHeight = firstVisiableChildView?.height
    return position * (itemHeight ?: 0) - (firstVisiableChildView?.top ?: 0)
}

/**
 * @Note   转换弱引用
 */
fun <T : Any> T.weak(): WeakReference<T> {
    return WeakReference(this)
}

fun Disposable.joinComposite(composite: CompositeDisposable) {
    composite.add(this)
}

/**
 * @Note   dp转px
 */
fun Int.dpToPx(): Int {
    return DisplayUtils.dip2px(BaseApplication.sApplication, this.toFloat())
}

/**
 * @Note   px转dp
 */
fun Int.pxToDp(): Int {
    return DisplayUtils.px2dip(BaseApplication.sApplication, this.toFloat())
}

/**
 * @Note   dp转px
 */
fun Double.dpToPx(): Int {
    return DisplayUtils.dip2px(BaseApplication.sApplication, this.toFloat())
}

/**
 * @Note   px转dp
 */
fun Double.pxToDp(): Int {
    return DisplayUtils.px2dip(BaseApplication.sApplication, this.toFloat())
}


/**
 * @Note   快速转换databinding字段
 */
fun <T> T.bindingParams(): ObservableField<T> {
    return ObservableField(this)
}

/**
 * @Note   以流的方式获取Json的字符串
 */
fun ResponseBody.getJsonString(): String {
    source().request(Long.MAX_VALUE)
    val buffer = source().buffer()
    return buffer.clone().readString(Charset.forName("UTF-8"))
}

fun ResponseBody.toJsonObject(): JSONObject {
    val jsonString = getJsonString()
    return if (jsonString.isEmpty()) {
        JSONObject()
    } else {
        JSONObject(jsonString)
    }
}

fun ResponseBody.toJsonArray(): JSONArray {
    val jsonString = getJsonString()
    return if (jsonString.isEmpty()) {
        JSONArray()
    } else {
        JSONArray(jsonString)
    }
}


/** 参数获取扩展方法 防止空值 */

fun JSONObject.valueString(key: String): String {
    return if (has(key) && !isNull(key)) {
        getString(key)
    } else {
        ""
    }
}

fun JSONObject.valueInt(key: String): Int {
    return if (has(key) && !isNull(key)) {
        getInt(key)
    } else {
        -1
    }
}

fun JSONObject.valueBool(key: String): Boolean {
    return if (has(key) && !isNull(key)) {
        getBoolean(key)
    } else {
        false
    }
}

fun JSONObject.valueDouble(key: String): Double {
    return if (has(key) && !isNull(key)) {
        getDouble(key)
    } else {
        -1.0
    }
}

fun JSONObject.valueDate(key: String): String {
    return if (has(key) && !isNull(key)) {
        WTimeUtils.toString(Date(valueLong(key) * 1000), null)
    } else {
        ""
    }
}

fun JSONObject.valueLong(key: String): Long {
    return if (has(key) && !isNull(key)) {
        getLong(key)
    } else {
        -1
    }
}

fun JSONObject.valueJsonObject(key: String): JSONObject {
    return if (has(key) && !isNull(key)) {
        getJSONObject(key)
    } else {
        JSONObject()
    }
}

fun JSONObject.valueJsonArray(key: String): JSONArray {
    return if (has(key) && !isNull(key)) {
        getJSONArray(key)
    } else {
        JSONArray()
    }
}

fun JSONArray.arrayObjects(): ArrayList<JSONObject> {

    var result = ArrayList<JSONObject>()

    for (i in 0..(this.length() - 1)) {
        result.add(getJSONObject(i))
    }

    return result

}

/**=================================================*/

fun View.visable() {
    this.visibility = View.VISIBLE
}

fun View.gone() {
    this.visibility = View.GONE
}

fun View.invisable() {
    this.visibility = View.INVISIBLE
}

/**============后期添加上的=====================================*/

fun startGoodsDetailActivity(context: Context, goodsId: Int) {
    if (context is AppCompatActivity) {
        (context as AppCompatActivity).push(ActCons.GoodsDetailActivity, {
            it.withInt("goodsId", goodsId)
        })
    } else {
        ARouter.getInstance().build(ActCons.GoodsDetailActivity).withInt("goodsId", goodsId).withTransition(R.anim.push_left_in, R.anim.push_left_out).navigation(context)
    }
}

fun startShopActivity(context: Context, shopId: Int) {
    if (context is AppCompatActivity) {
        (context as AppCompatActivity).push(ActCons.ShopActivity, {
            it.withInt("shopId", shopId)
        })
    } else {
        ARouter.getInstance().build(ActCons.ShopActivity).withInt("shopId", shopId).withTransition(R.anim.push_left_in, R.anim.push_left_out).navigation(context)
    }
}

/**
 * 新建fragment对象
 */
fun <T : Fragment> sNewStanceFragment(context: Context, clazz: Class<T>, bundle: Bundle?): T {
    return Fragment.instantiate(context, clazz.getName(), bundle) as T
}

/**
 * 新建fragment对象
 */
fun <T : Fragment> sNewStanceFragment(context: Context, clazz: Class<T>): T {
    return Fragment.instantiate(context, clazz.getName()) as T
}

/**
 * 新建空布局
 */
fun newEmptyView(context: Context): View {
    return View.inflate(context, R.layout.view_empty, null)
}

fun newDivider(context: Context): DividerItemDecoration {
    val dividerItemDecoration = DividerItemDecoration(context, DividerItemDecoration.VERTICAL)
    val drawable = ContextCompat.getDrawable(context, R.drawable.divider_1bdp)!!
    dividerItemDecoration.setDrawable(drawable)
    return dividerItemDecoration
}

fun FragmentActivity.openPicture(maxSelectNum: Int = 1, isSingle: Boolean = true, selectMedia: MutableList<LocalMedia>? = null, requestCode: Int = -1, callback: OnResultCallbackListener<LocalMedia>? = null) {
    RxPermissions(this)
            .request(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
            .subscribe {
                if (it) {
                    pictureSelectorConfig(PictureSelector.create(this),
                            maxSelectNum = maxSelectNum,
                            isSingle = isSingle,
                            selectMedia = selectMedia,
                            requestCode = requestCode,
                            callback = callback)
                }
            }
}

fun Fragment.openPicture(maxSelectNum: Int = 1, isSingle: Boolean = true, selectMedia: MutableList<LocalMedia>? = null, requestCode: Int = -1, callback: OnResultCallbackListener<LocalMedia>? = null) {
    RxPermissions(this)
            .request(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
            .subscribe {
                if (it) {
                    pictureSelectorConfig(PictureSelector.create(this),
                            maxSelectNum = maxSelectNum,
                            isSingle = isSingle,
                            selectMedia = selectMedia,
                            requestCode = requestCode,
                            callback = callback)
                }
            }
}

private fun pictureSelectorConfig(pictureSelector: PictureSelector, maxSelectNum: Int = 1, isSingle: Boolean = true, selectMedia: MutableList<LocalMedia>? = null, requestCode: Int = 0, callback: OnResultCallbackListener<LocalMedia>? = null) {
    val pictureSelectionModel = pictureSelector
            .openGallery(PictureMimeType.ofImage())
            .imageEngine(GlideEngine.createGlideEngine())// 外部传入图片加载引擎，必传项
            .theme(R.style.picture_default_style)// 主题样式设置 具体参考 values/styles
            .isPreviewImage(true)// 是否可预览图片
            .selectionMode(isSingle.judge(PictureConfig.SINGLE, PictureConfig.MULTIPLE))// 多选 or 单选
            .isCompress(true)// 是否压缩
            .isOpenClickSound(false)// 是否开启点击声音
            .maxSelectNum(maxSelectNum)
    if (callback != null) {
        pictureSelectionModel.forResult(callback);//结果回调onActivityResult code
    } else {
        if (requestCode !=-1) {
            pictureSelectionModel.forResult(requestCode);//结果回调onActivityResult code
        } else {
            pictureSelectionModel.forResult(PictureConfig.CHOOSE_REQUEST);//结果回调onActivityResult code
        }
    }
    selectMedia?.let {
        pictureSelectionModel.selectionData(selectMedia)
    }

}

//APP选择的语言
var appLanguageSelect by Preference(LocalManageUtil.APP_LANGUAGE_SELECT, -1)

//APP选择的货币,默认中国
var appCurrencySelect by Preference(LocalManageUtil.APP_CURRENCY_SELECT, 12)

//APP选择的国家公馆,默认中国
var appCountrySelect by Preference(LocalManageUtil.APP_COUNTRY_SELECT, 12)

fun resetMainActivity(activity: Activity) {
    try {
        val intent = Intent()
        intent.setClassName(activity, "com.asia5b.a5mall.home.activity.MainActivity")
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK)
        activity.startActivity(intent)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}


fun removeAllOffGoods(input: ArrayList<AbsGoodsModel>): ArrayList<AbsGoodsModel> {
    val iterator = input.iterator()
    while (iterator.hasNext()) {
        val next = iterator.next()
        if (next.absGoodsOff == 0) {
            iterator.remove()
        }
    }
    return input
}